package dao

import (
	"fmt"
	"log"

	"github.com/go-xorm/xorm"

	"im/common"
	"im/requests"
	"im/responses"

	"im/errcode"
	"im/model"
	"im/service/cache"
	"im/service/orm"
)

type GroupsUsersDao struct {
	db    *xorm.Engine
}

func NewGroupsUsersDao() *GroupsUsersDao {
	return &GroupsUsersDao{db: orm.GetDB()}
}

func (d *GroupsUsersDao) Create(users model.GroupsUsers) (int64, error) {
	return d.db.InsertOne(users)
}

func (d *GroupsUsersDao) RelationExist(appId uint, groupId int64, userId int64) *int8 {
	m := new(model.GroupsUsers)
	ok, err := d.db.Cols("status").Where("apps_id=?", appId).Where("group_id=?", groupId).
		Where("user_id=?", userId).Get(m)
	if !ok {
		if err != nil {
			log.Println("群老与用户关系缓存失败 原因:" + err.Error())
		}
		return nil
	}
	return &m.Status
}

func (d *GroupsUsersDao) GetCacheKey(appId uint, groupId int64, userId int64) string {
	return fmt.Sprintf("%d_%d_%d_%d", cache.GROUPS_USERS_MAP, appId, groupId, userId)
}

func (d *GroupsUsersDao) Update(appId uint, groupId int64, userId int64, data *model.GroupsUsers, cols ...string) (int64, error) {
	return d.db.Cols(cols...).Where("apps_id=?", appId).Where("group_id=?", groupId).Where("user_id=?", userId).Update(data)
}

func (d *GroupsUsersDao) IsManager(appId uint, groupId int64, userId int64) bool {
	groupsUsers := new(model.GroupsUsers)
	find, err := d.db.Cols("status").Where("apps_id=?", appId).Where("group_id=?", groupId).
		Where("user_id=?", userId).Get(groupsUsers)
	if err != nil {
		panic(err)
	}
	if !find {
		return false
	}
	if groupsUsers.Status == 0 || groupsUsers.Status == 1 {
		return true
	}
	return false
}

func (d *GroupsUsersDao) GetListByUserId(userId int64) (*[]model.Groups, error) {
	var list = &[]model.Groups{}
	err := d.db.Table("groups_users").Join("INNER", "groups_v1", "groups_users.group_id = groups_v1.id").
		Where("groups_users.user_id=?", userId).Where("groups_users.status=?", 1).
		Find(list)
	if err != nil {
		return list, errcode.NewError(errcode.DaoFailed, err)
	}
	return list, nil
}

type groupsUsersWithInfo struct {
	model.GroupsUsers
	model.Users
}

func (d *GroupsUsersDao) GetListByGroupId(groupId int64) ([]responses.GroupsUsers, error) {
	// var list = []groupsUsersWithInfo{}
	var result = []responses.GroupsUsers{}
	err := d.db.Table("groups_users").
		Cols("groups_users.*,users.avatar").
		Join("inner", "users", "users.id=groups_users.user_id").
		Where("group_id=?", groupId).Asc("role").Find(&result)
	if err != nil {
		return result, errcode.NewError(errcode.DaoFailed, err)
	}
	return result, nil
}

type UsersWithGroupName struct {
	model.Users `xorm:"extends"`
	Name   string `json:"name"`
}

func (d *GroupsUsersDao) GetCanPushUser(groupIds ...int64) ([]UsersWithGroupName, error) {
	var ms []UsersWithGroupName
	err := d.db.Table("groups_users").
		Cols("users.*,name").
		Join("inner", "users", "users.id=groups_users.user_id").
		Join("inner", "groups_v1", "groups_v1.id=groups_users.user_id").
		In("group_id", common.ToInterfaceSlice(groupIds)...).
		Where("posts_notify=?", model.PostsNotifyOn).
		Find(&ms)
	if err != nil {
		return ms, errcode.NewError(errcode.DaoFailed, err)
	}
	return ms, nil
}
func (d *GroupsUsersDao) GetRecommendGroups(user model.Users, param requests.GetRecommendGroups) ([]model.Groups, error) {
	var list []model.Groups
	joinedGroupIds, err := d.GetGroupIdListByUserId(user.Id)
	if err != nil {
		return list, errcode.NewError(errcode.DaoFailed, err)
	}
	list, err = NewGroupsDaoWithEs().GetRecommendedGroups(param.Location, joinedGroupIds, param.Pagination)
	return list, err
}

func (d *GroupsUsersDao) GetGroupIdListByUserId(userId int64) ([]int64, error) {
	var idList []int64
	list, err := d.GetListByUserId(userId)
	if err != nil {
		return idList, err
	}
	for _, g := range *list {
		idList = append(idList, g.Id)
	}
	return idList, nil
}

func (d *GroupsUsersDao) Modify(userId int64, data model.GroupsUsersModifiable) error {
	_, err := d.db.Where("user_id=?", userId).Update(model.GroupsUsers{
		GroupsUsersModifiable: data,
	})
	if err != nil {
		return errcode.NewError(errcode.DaoFailed, err)
	}
	return nil
}
